//
//  MABaseApplication.h
//  MiniApp
//
//  Created by zilinzhou on 2018/11/22.
//  Copyright © 2018 tencent. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "MAAppInfo.h"
#import "MAPackage.h"
#import "QMAJSPluginEngine.h"
#import "MAJSExecutorProtocol.h"
#import "MANavigationController.h"
#import "MABaseAppConfig.h"
#import "QMAEntryModel.h"
#import "QMAReportModel.h"
#import "MALocalServerProtocol.h"
#import "MAHeartbeatManager.h"
#import "QMAEntrySceneDefine.h"
#import "MAUIConfig.h"
NS_ASSUME_NONNULL_BEGIN

#define  QQ_MINIAPP_FAKEURL         @"https://m.q.qq.com/a"

#define  MALoadingViewControllerUpdateProgressNotify  @"__MALoadingViewControllerUpdateProgress__"
#define  QMAApplicationOnUnloadNotification  @"__QMAApplicationOnUnload__"
#define  QMAApplicationOnLoadNotification  @"__QMAApplicationOnLoad__"
#define  QMAApplicationOnShowNotification    @"__QMAApplicationOnShow__"
#define  QMAApplicationOnHideNotification    @"__QMAApplicationOnHide__"

// 最后一位为1 代表小程序展示
typedef NS_OPTIONS(NSUInteger, MAAppState) {
    MAAppStateNone = 0,
    MAAppStateShow = 0x1, //                                                           1
    MAAppStatePackageReady = 1 << 1, // packageReady                                   2
    MAAppStateColdLaunched = 1 << 2 | MAAppStateShow, // 冷启动完成                      5
    MAAppStateHotLaunched = 1 << 3 | MAAppStateShow, // 热启动完成                       9
    MAAppStateEnterForeground = 1 << 4 | MAAppStateShow, // 切前台                      17
    MAAppStateLeaveNativeVC = 1 << 5 | MAAppStateShow, // 从native页面回来               33
    MAAppStateLeaveAnotherMiniApp = 1 << 6 | MAAppStateShow, // 从另一个小程序回来        65
    MAAppStateEnterAnotherMiniApp = 1 << 7, // 呼起另一个小程序                          128
    MAAppStateEnterNativeVC = 1 << 8,// 进入native页面                                  256
    MAAppStateEnterBackground = 1 << 9, // 切后台                                       512
    MAAppStateCloseApp = 1 << 10, // 关闭小程序                                         1024
    // http://tapd.oa.com/IosQQ/bugtrace/bugs/view/1010066451075956539
    MAAppStateHotLaunchedReLaunch = 1 << 11 | MAAppStateShow, //热启动并且触发了reLaunch 2049
    MAAppStateWillTerminate = 1 << 12, // Terminate小程序                              4096

};

@class MAStorage;
@class MAFileManager;
@class MAAuthorizeManager;
@class MAWorkerManager;
@class MAVideoManager;
@class MALivePlayerManager;
@class MAAudioManager;
@class MANativeBufferPool;
@class MAGlobalStorage;
@class MADebugConnection;
@class MAWebViewController; // TODO: 要去掉相关接口，挪到MAApplication
@class FBLPromise<__covariant Value>;
@class MAAuthorizeDataManager;
@class MAKeyboardNotificationManager;

typedef void (^AlertCompleteBlcok)(void);
typedef void (^AlertBlock)(_Nullable AlertCompleteBlcok complete);

/// 小程序小游戏基类,挂载共用组件
@interface MABaseApplication : NSObject

@property (nonatomic, strong, nullable, readonly) MAAppInfo *recentlyModifiedAppInfo; // 在容器化小程序中存在将appInfo修改的逻辑。这里需要记录下老的那一份
@property (nonatomic, strong, readonly) MAAppInfo *appInfo;
@property (nonatomic, strong) MAAppInfo *hotLaunchAppInfo;
@property (nonatomic, strong, readonly) QMAEntryModel *entryModel;
@property (nonatomic, strong) QMAEntryModel *chatModel; // 分享面板最近联系人快速分享数据
@property (nonatomic, strong, readwrite) MABaseAppConfig *appConfig;
@property (nonatomic, strong, readonly) MAPackage *package;
@property (nonatomic, strong, readonly) QMAJSPluginEngine *jsPluginEngine;
@property (nonatomic, strong, readonly) id<MAJSExecutorProtocol> service;
@property (nonatomic, strong, readonly) MAStorage *storage;
@property (nonatomic, strong, readonly) MAGlobalStorage *globalStorage;
@property (nonatomic, strong, readonly) MAFileManager *maFileManager;
@property (nonatomic, strong, readonly) MAAuthorizeManager *authorizeManager;
@property (nonatomic, strong, readonly) MAAuthorizeDataManager *authDataManager;
@property (nonatomic, strong, readonly) MAWorkerManager *workerManager;
@property (nonatomic, strong, readonly) MANavigationController *rootViewController;
@property (nonatomic, weak, readonly) UIViewController *parentViewController; // 重启app时需要用到
@property (nonatomic, strong, readonly) MAAppInfo *updateAppInfo;
#if QMA_USE_VIDEO
@property (nonatomic, strong, readonly) MAVideoManager *videoManager;
#endif
@property (nonatomic, strong, readonly) MAAudioManager *audioManager;
@property (nonatomic, strong, readonly) MALivePlayerManager *livePlayerManager;
@property (nonatomic, strong, readonly) MANativeBufferPool *bufferPool;
@property (nonatomic, strong, readonly) MADebugConnection *debugConnection;
@property (nonatomic, strong, readonly) MAKeyboardNotificationManager *keyboardNotificationManager;
@property (nonatomic, strong) id<MALocalServerProtocol> localServer;
@property (nonatomic, assign, readwrite) BOOL isLaunchEnd;
@property (nonatomic, copy, nullable) NSArray<NSString *> *forwardMaterialPathArray;
// 上报相关，客户端生成的, 每次启动miniapp都要重新生成新的,
// 之前放在MiniSDK中不合理，小程序呼起小程序的时候，会有问题（同一个launchid下存在不同的appid）
@property (nonatomic, assign) int64_t launchId;

// 小程序间跳转，需要记录前一个小程序并处理它的onShow和onHide
@property (nonatomic, weak) MABaseApplication *fromApplication;
@property (nonatomic, assign) MAAppState appState; // TODO: 需要下沉到MAApplication.  前置工作: `上报逻辑接入流式处理框架`
@property (nonatomic, strong) NSDate *appStateModifyTime; // TODO: 下沉到MAApplication. 前置工作: `上报逻辑接入流式处理框架`

@property (nonatomic, strong) NSDictionary *referrerInfoBackFromApp; // 从另一个小程序回来的时候带的信息

@property (nonatomic, copy) void(^appOnClickClose)(MABaseApplication *application);

/// 进入小程序的场景值
@property (nonatomic, assign) MAEntryScene scene;

@property (nonatomic, strong, readonly) FBLPromise *restartPromise;
/*
 * 背景：  从小程序从 互联分享（场景值1036）或者1069打开时，小程序拥有打开App的能力
 *        当小程序从以下场景打开时，保持上一次打开小程序时打开App能力的状态
 *        从其他小程序返回小程序（场景值1038）
 *
 */
@property (nonatomic, assign) MAEntryScene initialScene;

/*
 版本更新相关，checkForUpdateBlock 内需执行 js 回调业务层，需在 appLaunch 之后执行.
 hasLaunch 初始为 NO 记录 checkForUpdateBlock, appLaunch 后置为 YES 时自动触发 checkForUpdateBlock 执行.
 */
@property (nonatomic, assign) BOOL hasLaunch;
@property (nonatomic, copy) void(^ _Nullable checkForUpdateBlock)(void);
@property (nonatomic, copy, readonly) NSDictionary <NSString *, NSNumber *>*apiPermission; // 一级黑白名单 黑名单为0 白名单为1
@property (nonatomic, copy, readonly) NSDictionary<NSString *, NSDictionary<NSString *, NSNumber *> *>*secondaryApiPermission;
@property (nonatomic, copy, readonly) NSArray<NSString *> *defaultBlackList; // 默认黑名单
@property (nonatomic, copy, readonly) NSArray<NSString *> *defaultSecondaryBlackList; // 二级默认黑名单，注意操作的也是二级对应的一级
@property (nonatomic, copy) AlertBlock delyAlertPermission;
@property (nonatomic, assign ) BOOL keepScreenOn;   // 保持屏幕亮度
@property (nonatomic, assign) BOOL shareWithShareTicket; // share if with share ticket
// 设置分享相关的参数 现在只有setMessageToFriendQuery这个API会用到
@property (nonatomic, strong) NSMutableDictionary *shareQuery;
@property (nonatomic, assign) BOOL appHasNewVersion; // appInfo是否更新了，appstore关闭的时候使用
@property (nonatomic, assign) BOOL isShowingBlueBar; // 是否正在显示aio小蓝条
@property (nonatomic, assign) BOOL isShowingFastShareTable; //是否正在显示快速分享面板
@property (nonatomic, assign) BOOL hideRestartButton; // 是否隐藏重启小程序选项
@property (nonatomic, assign) BOOL isExistInGroupApp; // 记录当前app是否已经加进entryData记录的群应用中

@property (nonatomic, strong) MAHeartbeatManager* heartbeatManager;//心跳控制器（目前仅应用于达人计时和小游戏防成迷系统）

@property (nonatomic, strong, nullable) QMAReport05115Model *report05115Model;

@property (nonatomic) CFTimeInterval videoAdvTime; // 用户观看视频广告的时长，用于上报

@property (nonatomic, assign) BOOL hasEnterBackground; // 手Q是否在后台

@property (nonatomic, assign) BOOL isAdShowing; // 广告是否显示

@property (nonatomic, strong, readonly) FBLPromise *onClosePromise;

/// 快速分享弹窗只支持竖屏，点击快速分享后，暂缓旋转屏幕
@property (nonatomic, assign) BOOL isDelayRotate;

- (instancetype)initWithAppInfo:(MAAppInfo *)appInfo;

// 更新QMAEntryModel，同时清除appUIConfig缓存
- (void)updateEntryModel:(QMAEntryModel *)entryModel;

/// 小程序UI配置
- (MAUIConfig *)appUIConfig;

/* 通知js是否有版本更新
 * updatedAppInfo : 新版本的appInfo
 */
- (void)updateAppIfNeeded:(MAAppInfo *)updatedAppInfo;

- (id<MALocalServerProtocol>)createLocalServer;

// for generate_func_ready
- (void)appLaunch NS_REQUIRES_SUPER;

// 统一顶层vc获取方法，具体类型各个业务自己判断；类型可能是MAWebViewController、TTViewController、MAMiniAppMainPageViewController等
- (UIViewController *)topViewController;

/// 是否正在loading，也即正处于loading页面
/// @return YES ,是
- (BOOL)isLoading;

- (UIView *)globalRightViewForPageURL:(NSString * _Nullable)pageURL;
- (UIImage *)globalLeftBtnImageForPageURL:(NSString * _Nullable)pageURL;
- (BOOL)isNeedBlackIcon:(NSString *_Nullable)pageURL;

/// 对所有参数进行ArrayBuffer编解码
- (NSDictionary *)arrayBufferUnpack:(NSDictionary *)data;
- (NSDictionary *)arrayBufferPack:(NSDictionary *)data;
/// 对单个参数进行ArrayBuffer编解码
- (NSData *)arrayBufferUnpackObject:(NSDictionary *)obj;
- (NSDictionary *)arrayBufferPackObject:(NSData *)obj;

// 是否展示"转发"按钮
- (void)setShowShareToAIO:(BOOL)showShareToAIO;
- (BOOL)showShareToAIO;

// 是否展示"分享到空间"按钮
- (void)setShowShareToQzone:(BOOL)showShareToQzone;
- (BOOL)showShareToQzone;

- (BOOL)showShareToWechatMoment;
- (void)setShowShareToWechatMoment:(BOOL)showShareToWechatMoment;

- (BOOL)showShareToWechatFriends;
- (void)setShowShareToWechatFriends:(BOOL)showShareToWechatFriends;

// 是否展示频道分享入口
- (BOOL)showShareToGuild;
// 设置是否展示频道分享入口
- (void)setShowShareToGuild:(BOOL)showShareToGuild;

- (void)reloadRightNaigationItem4MAChannel;

- (void)shareToAIO;
- (void)shareToQzone;
- (void)shareToGuild;
- (void)shareToWechatMoment;
- (void)shareToWechatFriends;
- (void)fastShareToQQ:(QMAEntryModel *)chatModel;
- (void)restartApplication;

// 增加到收藏 通知到基础库
- (void)addToFavorites:(BOOL)isFromBasicLibray;

// 小程序小游戏添加广告视图
- (void)addAdvView:(UIView *)advView;

// 关闭当前小程序，可带动画
- (void)closeApplicationAnimated:(BOOL)isAnimated completion:(void (^ _Nullable)(void))completion;

// 是否限制：1. 添加到我的，2. 添加到彩签，3. 保存到桌面
- (BOOL)isLimitedAccess;

// 是否支持IDE指定scene、appid、extraData(预览版/真机调试支持）
- (BOOL)isSupportIDEConfig;

// 05115表上报相关
- (void)addReport05115Block:(void(^)(void))block;

// 主题变化时通知
- (void)onThemeChangedTo:(BOOL)darkMode;

// Native的事件通知
- (void)onGeneralNativeEvent:(NSString *)event data:(NSDictionary *)data;

// 结束启动页面
- (void)endLaunchLoading;

// 回去当前的rootVC
- (UINavigationController *)getCurrentAppRootVC;

// 获取当前显示的容器化页面的webviewID
- (NSArray<NSNumber *> *)getCurrentShowedWebviewIDs;

// 触发回前台的操作
- (void)onAppEnterForegroundWithState:(MAAppState)state webviewIDs:(NSArray<NSNumber *> *)webviewIDs;

// 触发退后台操作
- (void)onAppEnterBackgroundWithState:(MAAppState)state webviewIDs:(NSArray<NSNumber *> *)webviewIDs;

//是否能够开始右滑返回
- (BOOL)shouldBeginRightDragToBack;

@end

NS_ASSUME_NONNULL_END
